package org.x.starter4j.mongojack;

import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import org.joda.time.DateTime;
import org.mongojack.DBQuery;
import org.mongojack.Id;
import org.mongojack.JacksonDBCollection;
import org.mongojack.ObjectId;
import org.mongojack.WriteResult;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
import org.x.starter4j.mongojack.App.Bike.Wheel;

/**
 * Hello world!
 * 
 */
public class App
{
	protected static DBCollection _Collection;

	protected static void initialize()
	{
		ServerAddress address = createServerAddress();
		_Collection = createCollection(address);
	}

	protected static ServerAddress createServerAddress()
	{
		ServerAddress address = null;
		try
		{
			address = new ServerAddress("127.0.0.1", 27017);
		}
		catch (UnknownHostException e)
		{
		}
		return address;
	}

	protected static DBCollection createCollection(final ServerAddress address)
	{
		MongoClient mongoClient = new MongoClient(address);
		DB db = mongoClient.getDB("test");
		String collectionName = String.format("%s.%s", "test_collection", "subcollection");
		DBCollection collection = db.getCollection(collectionName);
		return collection;
	}

	public static void main(final String[] args)
	{
		System.out.println("Hello World!");
		System.out.println("======================================");
		System.out.println("开始初始化MongoDb相关...");
		initialize();
		System.out.println("初始化MongoDb完成!");

		System.out.println("JacksonDBCollection.wrap(_Collection, Bike.class, String.class)");
		JacksonDBCollection<Bike, String> coll = JacksonDBCollection.wrap(_Collection, Bike.class, String.class);
		coll.drop();
		System.out.println("清除数据库内容完成!");

		System.out.println();
		System.out.println("====> CRUD:Create...");
		List<String> ids = new ArrayList<>();
		for (int n = 1; n <= 300; n++)
		{
			Bike bike = new Bike();
			bike.setBrand(String.format("brand-%s", n));
			bike.setBuyTime(DateTime.now());
			List<Short> gears = new ArrayList<>();
			for (short i = 1; i <= 5; i++)
			{
				gears.add((short) (i * 5));
			}
			bike.setGears(gears);
			bike.setIsBlack((n % 2) == 0);
			bike.setName(UUID.randomUUID().toString().substring(0, 6).toUpperCase());
			bike.setWeight(567 * n);
			bike.setPrice(n * 2.85);
			bike.setBikeColor(((n % 2) == 0) ? BikeColor.Green : BikeColor.Red);
			bike.setWheel(new Wheel(String.valueOf(n), n * 987654));

			WriteResult<Bike, String> result = coll.insert(bike);
			String id = result.getSavedId();
			ids.add(id);
		}
		System.out.println("向数据插入数据完成,共计" + ids.size() + "条");
		System.out.println("从数据库中取出数据，并抽样打印：");
		for (int i = 0; i < ids.size(); i++)
		{
			Bike queryBike = coll.findOneById(ids.get(i));
			if ((i % 50) == 0)
			{
				System.out.println(queryBike);
			}
		}

		System.out.println();
		System.out.println("====> CRUD:Update...");

		String id = ids.get(ids.size() - 1);
		Bike oldBike = coll.findOneById(id);
		System.out.println(oldBike);

		coll.update(DBQuery.is("_id", id), new Bike());
		System.out.println(String.format("更新的记录的ID是：", id));
		Bike updateBike = coll.findOneById(id);
		System.out.println(updateBike);
		// DBCursor<Bike> cursor = coll.find(DBQuery.or(
		// DBQuery.is("author", "jsmith"),
		// DBQuery.size("comments", 3)));
	}

	public static class Bike
	{
		private String id;
		private String name;
		private boolean isBlack;
		private int weight;
		private DateTime buyTime;
		private String brand;
		private List<Short> gears;
		private double price;
		private BikeColor bikeColor;
		private Wheel wheel;

		@Id
		@ObjectId
		public String getId()
		{
			return id;
		}

		@Id
		@ObjectId
		public void setId(final String id)
		{
			this.id = id;
		}

		public String getName()
		{
			return name;
		}

		public void setName(final String name)
		{
			this.name = name;
		}

		public boolean getIsBlack()
		{
			return isBlack;
		}

		public void setIsBlack(final boolean isBlack)
		{
			this.isBlack = isBlack;
		}

		public int getWeight()
		{
			return weight;
		}

		public void setWeight(final int weight)
		{
			this.weight = weight;
		}

		@JsonSerialize(using = DateTimeSerializer.class)
		public DateTime getBuyTime()
		{
			return buyTime;
		}

		public void setBuyTime(final DateTime buyTime)
		{
			this.buyTime = buyTime;
		}

		public String getBrand()
		{
			return brand;
		}

		public void setBrand(final String brand)
		{
			this.brand = brand;
		}

		public List<Short> getGears()
		{
			return gears;
		}

		public void setGears(final List<Short> gears)
		{
			this.gears = gears;
		}

		public double getPrice()
		{
			return price;
		}

		public void setPrice(final double price)
		{
			this.price = price;
		}

		public BikeColor getBikeColor()
		{
			return bikeColor;
		}

		public void setBikeColor(final BikeColor bikeColor)
		{
			this.bikeColor = bikeColor;
		}

		public Wheel getWheel()
		{
			return wheel;
		}

		public void setWheel(final Wheel wheel)
		{
			this.wheel = wheel;
		}

		@Override
		public String toString()
		{
			StringBuilder builder = new StringBuilder();
			builder.append("Bike [id=").append(id).append(", name=").append(name).append(", isBlack=").append(isBlack).append(", weight=").append(weight).append(", buyTime=").append(buyTime).append(", brand=").append(brand).append(", gears=").append(gears).append(", price=").append(price).append(", bikeColor=").append(bikeColor).append(", wheel=").append(wheel).append("]");
			return builder.toString();
		}

		public static class Wheel
		{
			public Wheel()
			{
			}

			public Wheel(final String shoe, final long diameter)
			{
				this.shoe = shoe;
				this.diameter = diameter;
			}

			private String shoe;
			private long diameter;

			public String getShoe()
			{
				return shoe;
			}

			public void setShoe(final String shoe)
			{
				this.shoe = shoe;
			}

			public long getDiameter()
			{
				return diameter;
			}

			public void setDiameter(final long diameter)
			{
				this.diameter = diameter;
			}

			@Override
			public String toString()
			{
				return String.format("Wheel [shoe=%s, diameter=%s]", shoe, diameter);
			}

		}

	}

	public enum BikeColor
	{
		Red, Green, Yellow, White
	}
}
